import os
import json
import logging
import requests
from datetime import datetime, timedelta

from django.conf import settings
from django.contrib.auth import get_user_model
from django.utils import timezone
from django.db import transaction

from rest_framework import status, viewsets, mixins
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.decorators import action, permission_classes
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework_simplejwt.views import (
    TokenRefreshView, TokenVerifyView, TokenBlacklistView as BaseTokenBlacklistView
)


from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiExample
from drf_spectacular.types import OpenApiTypes

from .models import WechatAuth, SmsVerification, LoginLog, BlacklistedToken
from .serializers import (
    WechatLoginSerializer, SmsVerificationSerializer, SmsLoginSerializer,
    TokenRefreshSerializer, TokenVerifySerializer, TokenBlacklistSerializer,
    UserInfoSerializer
)
from .utils import refresh_user_token

User = get_user_model()
logger = logging.getLogger(__name__)


class WechatLoginView(APIView):
    """微信小程序登录视图"""
    
    permission_classes = [AllowAny]
    serializer_class = WechatLoginSerializer
    
    @extend_schema(
        summary="微信登录",
        description="使用微信小程序登录凭证code进行登录，如果用户不存在则自动创建。"
                    "登录成功后，系统会生成JWT令牌并存储到用户表中。",
        request=WechatLoginSerializer,
        responses={
            200: {
                'type': 'object',
                'properties': {
                    'refresh': {'type': 'string', 'description': '刷新令牌'},
                    'access': {'type': 'string', 'description': '访问令牌'},
                    'user': {
                        'type': 'object',
                        'properties': {
                            'id': {'type': 'integer', 'description': '用户ID'},
                            'phone': {'type': 'string', 'description': '手机号'},
                            'avatar': {'type': 'string', 'description': '头像URL'},
                            'date_joined': {'type': 'string', 'format': 'date-time', 'description': '注册时间'},
                            'last_login': {'type': 'string', 'format': 'date-time', 'description': '最后登录时间'}
                        }
                    },
                    'is_new_user': {'type': 'boolean', 'description': '是否为新用户'},
                    'needs_phone_binding': {'type': 'boolean', 'description': '是否需要绑定手机号'}
                },
                'description': '微信登录成功，返回访问令牌、刷新令牌和用户信息。'
                          '令牌信息也会同步存储到用户表中，供后续自动刷新使用。'
            },
            400: {
                'type': 'object',
                'properties': {
                    'error': {'type': 'string', 'description': '错误信息'}
                },
                'description': '登录失败，微信凭证无效或已过期'
            }
        },
        tags=["Authentication"]
    )
    def post(self, request):
        """
        微信小程序登录
        
        使用微信小程序登录凭证code进行登录，如果用户不存在则自动创建。
        
        登录成功后，系统会:
        1. 生成JWT访问令牌和刷新令牌
        2. 将令牌信息存储到用户表中（access_token和refresh_token字段）
        3. 更新用户的最后登录时间
        4. 记录登录日志
        5. 返回令牌和用户信息给前端
        
        前端收到响应后应该:
        1. 存储访问令牌用于后续API请求认证
        2. 安全存储刷新令牌用于令牌刷新
        3. 设置定时器定期调用自动刷新接口保持会话有效性
        """
        serializer = WechatLoginSerializer(data=request.data)
        if not serializer.is_valid():
            # 记录登录失败日志
            LoginLog.objects.create(
                login_type=LoginLog.Type.WECHAT,
                status=LoginLog.Status.FAILED,
                ip_address=self.get_client_ip(request),
                user_agent=request.META.get('HTTP_USER_AGENT'),
                device_id=request.data.get('device_id'),
                error_message=str(serializer.errors)
            )
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        
        code = serializer.validated_data.get('code')
        user_info = serializer.validated_data.get('user_info', {})
        phone = serializer.validated_data.get('phone')
        
        # 获取微信小程序配置
        appid = os.getenv('WX_APPID')
        secret = os.getenv('WX_SECRET')
        
        if not appid or not secret:
            error_msg = '微信小程序配置不完整'
            # 记录登录失败日志
            LoginLog.objects.create(
                login_type=LoginLog.Type.WECHAT,
                status=LoginLog.Status.FAILED,
                ip_address=self.get_client_ip(request),
                user_agent=request.META.get('HTTP_USER_AGENT'),
                device_id=request.data.get('device_id'),
                error_message=error_msg
            )
            return Response(
                {'error': error_msg},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
        
        # 请求微信API获取openid和session_key
        try:
            url = f'https://api.weixin.qq.com/sns/jscode2session?appid={appid}&secret={secret}&js_code={code}&grant_type=authorization_code'
            response = requests.get(url, timeout=10)
            data = response.json()
            
            if 'errcode' in data and data['errcode'] != 0:
                error_msg = f"微信登录失败: {data.get('errmsg', '未知错误')}"
                logger.error(error_msg)
                # 记录登录失败日志
                LoginLog.objects.create(
                    login_type=LoginLog.Type.WECHAT,
                    status=LoginLog.Status.FAILED,
                    ip_address=self.get_client_ip(request),
                    user_agent=request.META.get('HTTP_USER_AGENT'),
                    device_id=request.data.get('device_id'),
                    error_message=error_msg
                )
                return Response(
                    {'error': error_msg},
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            openid = data.get('openid')
            session_key = data.get('session_key')
            unionid = data.get('unionid')
            
            if not openid:
                error_msg = '获取openid失败'
                # 记录登录失败日志
                LoginLog.objects.create(
                    login_type=LoginLog.Type.WECHAT,
                    status=LoginLog.Status.FAILED,
                    ip_address=self.get_client_ip(request),
                    user_agent=request.META.get('HTTP_USER_AGENT'),
                    device_id=request.data.get('device_id'),
                    error_message=error_msg
                )
                return Response(
                    {'error': error_msg},
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            # 查找或创建用户
            with transaction.atomic():
                try:
                    wechat_auth = WechatAuth.objects.select_related('user').get(openid=openid)
                    user = wechat_auth.user
                    
                    # 更新session_key
                    wechat_auth.session_key = session_key
                    if unionid:
                        wechat_auth.unionid = unionid
                    
                    # 更新微信用户信息
                    if user_info:
                        wechat_auth.nickname = user_info.get('nickName')
                        wechat_auth.avatar_url = user_info.get('avatarUrl')
                        wechat_auth.gender = user_info.get('gender')
                        wechat_auth.country = user_info.get('country')
                        wechat_auth.province = user_info.get('province')
                        wechat_auth.city = user_info.get('city')
                        wechat_auth.language = user_info.get('language')
                    
                    wechat_auth.last_login = timezone.now()
                    wechat_auth.save()
                    
                except WechatAuth.DoesNotExist:
                    # 创建新用户
                    if phone:
                        # 如果提供了手机号，查找是否已存在该手机号的用户
                        try:
                            user = User.objects.get(phone=phone)
                        except User.DoesNotExist:
                            user = User.objects.create(
                                phone=phone,
                                openid=openid,
                                avatar=user_info.get('avatarUrl') if user_info else None
                            )
                    else:
                        # 如果没有提供手机号，创建一个临时用户，后续需要绑定手机号
                        user = User.objects.create(
                            phone=f"wx_{openid[:8]}",  # 临时手机号
                            openid=openid,
                            avatar=user_info.get('avatarUrl') if user_info else None
                        )
                    
                    # 创建微信认证信息
                    WechatAuth.objects.create(
                        user=user,
                        openid=openid,
                        session_key=session_key,
                        unionid=unionid,
                        nickname=user_info.get('nickName') if user_info else None,
                        avatar_url=user_info.get('avatarUrl') if user_info else None,
                        gender=user_info.get('gender') if user_info else None,
                        country=user_info.get('country') if user_info else None,
                        province=user_info.get('province') if user_info else None,
                        city=user_info.get('city') if user_info else None,
                        language=user_info.get('language') if user_info else None,
                        last_login=timezone.now()
                    )
            
            # 更新用户的最后登录时间
            user.last_login = timezone.now()
            user.save(update_fields=['last_login'])
            
            # 记录登录日志
            LoginLog.objects.create(
                user=user,
                login_type=LoginLog.Type.WECHAT,
                status=LoginLog.Status.SUCCESS,
                ip_address=self.get_client_ip(request),
                user_agent=request.META.get('HTTP_USER_AGENT'),
                device_id=request.data.get('device_id')
            )
            
            # 生成JWT令牌
            refresh = RefreshToken.for_user(user)
            
            # 将JWT令牌存储到用户表中
            user.access_token = str(refresh.access_token)
            user.refresh_token = str(refresh)
            user.save(update_fields=['access_token', 'refresh_token'])
            
            return Response({
                'refresh': str(refresh),
                'access': str(refresh.access_token),
                'user': UserInfoSerializer(user).data,
                'is_new_user': wechat_auth.created_at == wechat_auth.updated_at,
                'needs_phone_binding': not phone and user.phone.startswith('wx_')
            })
            
        except requests.RequestException as e:
            error_msg = f"微信接口调用失败: {str(e)}"
            logger.exception(error_msg)
            # 记录登录失败日志
            LoginLog.objects.create(
                login_type=LoginLog.Type.WECHAT,
                status=LoginLog.Status.FAILED,
                ip_address=self.get_client_ip(request),
                user_agent=request.META.get('HTTP_USER_AGENT'),
                device_id=request.data.get('device_id'),
                error_message=error_msg
            )
            return Response(
                {'error': '网络请求失败，请稍后再试'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
        except Exception as e:
            error_msg = f"微信登录异常: {str(e)}"
            logger.exception(error_msg)
            # 记录登录失败日志
            LoginLog.objects.create(
                login_type=LoginLog.Type.WECHAT,
                status=LoginLog.Status.FAILED,
                ip_address=self.get_client_ip(request),
                user_agent=request.META.get('HTTP_USER_AGENT'),
                device_id=request.data.get('device_id'),
                error_message=error_msg
            )
            return Response(
                {'error': '系统异常，请稍后再试'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
    
    def get_client_ip(self, request):
        """获取客户端IP地址"""
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = request.META.get('REMOTE_ADDR')
        return ip


class SmsVerificationView(APIView):
    """短信验证码视图"""
    
    permission_classes = [AllowAny]
    serializer_class = SmsVerificationSerializer
    
    @extend_schema(
        summary="发送短信验证码",
        description="向指定手机号发送短信验证码",
        request=SmsVerificationSerializer,
        responses={
            200: {
                'type': 'object',
                'properties': {
                    'message': {'type': 'string', 'description': '响应消息'}
                }
            },
            400: {
                'type': 'object',
                'properties': {
                    'error': {'type': 'string', 'description': '错误信息'}
                }
            },
            429: {
                'type': 'object',
                'properties': {
                    'error': {'type': 'string', 'description': '错误信息'}
                }
            }
        },
        tags=["Authentication"]
    )
    def post(self, request):
        """
        发送短信验证码
        
        向指定手机号发送短信验证码
        """
        serializer = SmsVerificationSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        
        phone = serializer.validated_data.get('phone')
        purpose = serializer.validated_data.get('purpose')
        
        # 检查是否频繁发送
        last_minute = timezone.now() - timedelta(minutes=1)
        if SmsVerification.objects.filter(phone=phone, created_at__gt=last_minute).exists():
            return Response(
                {'error': '发送过于频繁，请稍后再试'},
                status=status.HTTP_429_TOO_MANY_REQUESTS
            )
        
        # 生成验证码
        import random
        code = ''.join(random.choices('0123456789', k=6))
        
        # 设置过期时间
        expires_at = timezone.now() + timedelta(minutes=5)
        
        # 保存验证码
        SmsVerification.objects.create(
            phone=phone,
            code=code,
            purpose=purpose,
            expires_at=expires_at
        )
        
        # 调用短信发送服务发送验证码
        from notification_app.utils import send_sms
        
        # 根据不同用途构建不同的短信内容
        if purpose == SmsVerification.Purpose.LOGIN:
            content = f"【沥青运输】您的登录验证码是：{code}，5分钟内有效，请勿泄露给他人。"
        elif purpose == SmsVerification.Purpose.REGISTER:
            content = f"【沥青运输】您的注册验证码是：{code}，5分钟内有效，请勿泄露给他人。"
        elif purpose == SmsVerification.Purpose.RESET_PASSWORD:
            content = f"【沥青运输】您的重置密码验证码是：{code}，5分钟内有效，请勿泄露给他人。"
        else:
            content = f"【沥青运输】您的验证码是：{code}，5分钟内有效，请勿泄露给他人。"
        
        # 发送短信
        send_result = send_sms(phone=phone, content=content)
        
        if not send_result:
            logger.error(f"向 {phone} 发送验证码失败")
            return Response(
                {'error': '短信发送失败，请稍后再试'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
        
        logger.info(f"向 {phone} 发送验证码: {code}, 用途: {purpose}")
        
        return Response({'message': '验证码已发送', 'code': code})


class SmsLoginView(APIView):
    """短信登录视图"""
    
    permission_classes = [AllowAny]
    
    @extend_schema(
        summary="短信验证码登录",
        description="使用手机号和短信验证码进行登录，如果用户不存在则自动创建。"
                    "登录成功后，系统会生成JWT令牌并存储到用户表中。",
        request=SmsLoginSerializer,
        responses={
            200: {
                'type': 'object',
                'properties': {
                    'refresh': {'type': 'string', 'description': '刷新令牌'},
                    'access': {'type': 'string', 'description': '访问令牌'},
                    'user': {
                        'type': 'object',
                        'properties': {
                            'id': {'type': 'integer', 'description': '用户ID'},
                            'phone': {'type': 'string', 'description': '手机号'},
                            'role': {'type': 'string', 'description': '用户角色'},
                            'avatar': {'type': 'string', 'description': '头像URL'},
                            'company': {'type': 'string', 'description': '公司名称'},
                            'credit_score': {'type': 'number', 'description': '信用评分'},
                            'date_joined': {'type': 'string', 'format': 'date-time', 'description': '注册时间'},
                            'last_login': {'type': 'string', 'format': 'date-time', 'description': '最后登录时间'}
                        }
                    },
                    'is_new_user': {'type': 'boolean', 'description': '是否为新用户'}
                },
                'description': '登录成功，返回访问令牌、刷新令牌和用户信息。'
                          '令牌信息也会同步存储到用户表中，供后续自动刷新使用。'
            },
            400: {
                'type': 'object',
                'properties': {
                    'error': {'type': 'string', 'description': '错误信息'}
                },
                'description': '登录失败，验证码无效或已过期'
            }
        },
        tags=["Authentication"],
        examples=[
            OpenApiExample(
                '短信登录请求示例',
                summary='短信登录请求示例',
                description='使用手机号和验证码进行登录的请求示例',
                value={
                    'phone': '13800138000',
                    'code': '123456'
                },
                request_only=True
            ),
            OpenApiExample(
                '短信登录响应示例',
                summary='短信登录响应示例',
                description='短信登录成功的响应示例',
                value={
                    'refresh': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTc2NzIyNTU5OSwiaWF0IjoxNzM1NjkyNzk5LCJqdGkiOiJjYzQ3YWY2NjM4YzQ0YjFhYmM3ZTQ0MzQ2IiwidXNlcl9pZCI6MX0.XZd2zvZb2vZJd3p3p3p3p3p3p3p3p3p3p3p3p3p3p3p',
                    'access': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzM1Njk2MTk5LCJpYXQiOjE3MzU2OTI1OTksImp0aSI6ImQ0NjZhYjM4YjY0NzQ4Y2FiYzdlNDQzNDYiLCJ1c2VyX2lkIjoxfQ.7qZ4QJz4QJz4QJz4QJz4QJz4QJz4QJz4QJz4QJz4QJz',
                    'user': {
                        'id': 1,
                        'phone': '13800138000',
                        'role': 'shipper',
                        'avatar': 'https://example.com/avatar.jpg',
                        'company': 'ABC物流公司',
                        'credit_score': '4.8',
                        'date_joined': '2024-01-01T10:00:00Z',
                        'last_login': '2024-01-15T14:30:00Z'
                    },
                    'is_new_user': False
                },
                response_only=True
            )
        ]
    )
    def post(self, request):
        """
        短信验证码登录
        
        使用手机号和短信验证码进行登录，如果用户不存在则自动创建。
        
        登录成功后，系统会:
        1. 生成JWT访问令牌和刷新令牌
        2. 将令牌信息存储到用户表中（access_token和refresh_token字段）
        3. 更新用户的最后登录时间
        4. 记录登录日志
        5. 返回令牌和用户信息给前端
        
        前端收到响应后应该:
        1. 存储访问令牌用于后续API请求认证
        2. 安全存储刷新令牌用于令牌刷新
        3. 设置定时器定期调用自动刷新接口保持会话有效性
        """
        serializer = SmsLoginSerializer(data=request.data)
        if not serializer.is_valid():
            # 记录登录失败日志
            LoginLog.objects.create(
                login_type=LoginLog.Type.SMS,
                status=LoginLog.Status.FAILED,
                ip_address=self.get_client_ip(request),
                user_agent=request.META.get('HTTP_USER_AGENT'),
                device_id=request.data.get('device_id'),
                error_message=str(serializer.errors)
            )
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        
        phone = serializer.validated_data.get('phone')
        code = serializer.validated_data.get('code')
        
        # 验证短信验证码
        now = timezone.now()
        try:
            sms_verification = SmsVerification.objects.filter(
                phone=phone,
                code=code,
                purpose=SmsVerification.Purpose.LOGIN,
                is_used=False,
                expires_at__gt=now
            ).latest('created_at')
        except SmsVerification.DoesNotExist:
            error_msg = '验证码无效或已过期'
            # 记录登录失败日志
            LoginLog.objects.create(
                login_type=LoginLog.Type.SMS,
                status=LoginLog.Status.FAILED,
                ip_address=self.get_client_ip(request),
                user_agent=request.META.get('HTTP_USER_AGENT'),
                device_id=request.data.get('device_id'),
                error_message=error_msg
            )
            return Response(
                {'error': error_msg},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # 标记验证码为已使用
        sms_verification.is_used = True
        sms_verification.used_at = now
        sms_verification.save()
        
        # 查找或创建用户
        try:
            user = User.objects.get(phone=phone)
            is_new_user = False
        except User.DoesNotExist:
            user = User.objects.create(phone=phone)
            is_new_user = True
        
        # 更新用户的最后登录时间
        user.last_login = timezone.now()
        user.save(update_fields=['last_login'])
        
        # 记录登录日志
        LoginLog.objects.create(
            user=user,
            login_type=LoginLog.Type.SMS,
            status=LoginLog.Status.SUCCESS,
            ip_address=self.get_client_ip(request),
            user_agent=request.META.get('HTTP_USER_AGENT'),
            device_id=request.data.get('device_id')
        )
        
        # 生成JWT令牌
        refresh = RefreshToken.for_user(user)
        
        # 将JWT令牌存储到用户表中
        user.access_token = str(refresh.access_token)
        user.refresh_token = str(refresh)
        user.save(update_fields=['access_token', 'refresh_token'])
        
        # 更新用户最后登录时间
        user.last_login = timezone.now()
        user.save(update_fields=['last_login'])
        
        return Response({
            'refresh': str(refresh),
            'access': str(refresh.access_token),
            'user': UserInfoSerializer(user).data,
            'is_new_user': is_new_user
        }, status=status.HTTP_200_OK)
    
    def get_client_ip(self, request):
        """获取客户端IP地址"""
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = request.META.get('REMOTE_ADDR')
        return ip


@extend_schema(
    summary="刷新访问令牌",
    description="使用刷新令牌获取新的访问令牌，如果启用令牌轮换，还会返回新的刷新令牌。"
                "刷新成功后，系统会同步更新用户表中的令牌信息。",
    request=TokenRefreshSerializer,
    responses={
        200: {
            'type': 'object',
            'properties': {
                'access': {'type': 'string', 'description': '新的访问令牌'},
                'refresh': {'type': 'string', 'description': '新的刷新令牌（仅在启用令牌轮换时返回）'}
            },
            'description': '令牌刷新成功，返回新的访问令牌，如果启用令牌轮换还会返回新的刷新令牌。'
                      '新的令牌信息会同步更新到用户表中。'
        },
        400: {
            'type': 'object',
            'properties': {
                'error': {'type': 'string', 'description': '错误信息'},
                'code': {'type': 'string', 'description': '错误代码'}
            },
            'description': '令牌刷新失败，可能是令牌无效或已过期'
        },
        401: {
            'type': 'object',
            'properties': {
                'detail': {'type': 'string', 'description': '错误详情'}
            },
            'description': '认证失败，刷新令牌已在黑名单中'
        }
    },
    tags=["Authentication"]
)
class CustomTokenRefreshView(TokenRefreshView):
    """自定义令牌刷新视图"""
    
    serializer_class = TokenRefreshSerializer
    
    def post(self, request, *args, **kwargs):
        """
        刷新访问令牌
        
        使用有效的刷新令牌获取新的访问令牌，如果启用令牌轮换，还会返回新的刷新令牌。
        
        刷新成功后，系统会:
        1. 验证刷新令牌的有效性
        2. 生成新的访问令牌
        3. 如果启用令牌轮换，生成新的刷新令牌
        4. 将新的令牌信息同步更新到用户表中
        5. 返回新的令牌给前端
        
        前端收到响应后应该:
        1. 更新本地存储的访问令牌
        2. 如果返回了新的刷新令牌，更新本地存储的刷新令牌
        3. 设置下一次刷新的定时器
        """
        # 检查刷新令牌是否在黑名单中
        refresh_token = request.data.get('refresh')
        if BlacklistedToken.objects.filter(token=refresh_token, expires_at__gt=timezone.now()).exists():
            return Response(
                {'detail': '刷新令牌已在黑名单中'},
                status=status.HTTP_401_UNAUTHORIZED
            )
        
        # 调用父类方法处理刷新逻辑
        try:
            response = super().post(request, *args, **kwargs)
            
            # 如果刷新成功，更新用户表中的令牌
            if response.status_code == status.HTTP_200_OK:
                # 获取用户
                from rest_framework_simplejwt.tokens import RefreshToken as JWTRerefshToken
                try:
                    refresh_token_obj = JWTRerefshToken(refresh_token)
                    user_id = refresh_token_obj['user_id']
                    user = User.objects.get(id=user_id)
                    
                    # 使用工具函数刷新令牌
                    token_data = refresh_user_token(user)
                    response.data['access'] = token_data['access']
                    if 'refresh' in token_data:
                        response.data['refresh'] = token_data['refresh']
                        
                except Exception as e:
                    logger.exception("更新用户令牌失败")
            
            return response
        except TokenError as e:
            logger.exception("令牌刷新异常")
            return Response(
                {'detail': f'令牌刷新失败: {str(e)}'},
                status=status.HTTP_400_BAD_REQUEST
            )
        except Exception as e:
            logger.exception("令牌刷新异常")
            return Response(
                {'detail': f'令牌刷新失败: {str(e)}'},
                status=status.HTTP_400_BAD_REQUEST
            )


class CustomTokenVerifyView(TokenVerifyView):
    """自定义令牌验证视图"""
    
    serializer_class = TokenVerifySerializer
    
    @extend_schema(
        summary="验证访问令牌",
        description="验证访问令牌的有效性",
        tags=["Authentication"]
    )
    def post(self, request, *args, **kwargs):
        """
        验证访问令牌
        
        验证提供的访问令牌是否有效
        """
        return super().post(request, *args, **kwargs)


class TokenAutoRefreshView(APIView):
    """自动刷新令牌视图"""
    
    permission_classes = [IsAuthenticated]
    serializer_class = TokenRefreshSerializer  # 添加序列化器类以解决OpenAPI警告
    
    @extend_schema(
        summary="自动刷新访问令牌",
        description="为当前认证用户自动刷新访问令牌，并同步更新用户表中的令牌信息。"
                    "该接口用于前端定时调用，以保持用户会话的有效性。",
        request=TokenRefreshSerializer,
        responses={
            200: {
                'type': 'object',
                'properties': {
                    'access': {'type': 'string', 'description': '新的访问令牌'},
                    'refresh': {'type': 'string', 'description': '新的刷新令牌'}
                },
                'description': '令牌刷新成功，返回新的访问令牌和刷新令牌'
            },
            400: {
                'type': 'object',
                'properties': {
                    'detail': {'type': 'string', 'description': '错误详情'}
                },
                'description': '请求参数错误或令牌刷新失败'
            },
            401: {
                'type': 'object',
                'properties': {
                    'detail': {'type': 'string', 'description': '错误详情'}
                },
                'description': '用户未认证或令牌无效'
            }
        },
        tags=["Authentication"]
    )
    def post(self, request):
        """
        自动刷新访问令牌
        
        该接口会:
        1. 使用当前用户的刷新令牌生成新的访问令牌
        2. 如果启用了令牌轮换，会生成新的刷新令牌
        3. 将新的令牌信息同步更新到用户表中
        4. 返回新的令牌给前端
        
        前端应该在收到响应后更新本地存储的令牌，并设置下一次刷新的定时器。
        """
        try:
            user = request.user
            
            # 使用工具函数刷新令牌
            token_data = refresh_user_token(user)
            
            return Response(token_data, status=status.HTTP_200_OK)
            
        except ValueError as e:
            return Response(
                {'detail': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
        except Exception as e:
            logger.exception("自动刷新令牌失败")
            return Response(
                {'detail': '令牌刷新失败'},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )


class UserInfoView(APIView):
    """获取当前用户信息视图"""
    
    permission_classes = [IsAuthenticated]
    
    @extend_schema(
        summary="获取当前用户信息",
        description="获取当前认证用户的详细信息，包括JWT令牌",
        responses={
            200: {
                'type': 'object',
                'properties': {
                    'id': {'type': 'integer', 'description': '用户ID'},
                    'phone': {'type': 'string', 'description': '手机号'},
                    'openid': {'type': 'string', 'description': '微信OpenID'},
                    'role': {'type': 'string', 'description': '用户角色'},
                    'role_authstatus': {'type': 'boolean', 'description': '角色认证状态'},
                    'avatar': {'type': 'string', 'description': '头像URL'},
                    'company': {'type': 'string', 'description': '公司名称'},
                    'credit_score': {'type': 'number', 'format': 'float', 'description': '信用评分'},
                    'access_token': {'type': 'string', 'description': '访问令牌'},
                    'refresh_token': {'type': 'string', 'description': '刷新令牌'},
                    'date_joined': {'type': 'string', 'format': 'date-time', 'description': '注册时间'},
                    'last_login': {'type': 'string', 'format': 'date-time', 'description': '最后登录时间'}
                },
                'description': '当前认证用户的详细信息，包括用于API认证的JWT令牌'
            }
        },
        tags=["Authentication"]
    )
    def get(self, request):
        """
        获取当前认证用户的详细信息
        
        返回当前用户的完整信息，包括：
        1. 基本身份信息（ID、手机号、微信OpenID）
        2. 角色信息和认证状态
        3. 企业信息（公司名称、信用评分）
        4. JWT令牌信息（访问令牌、刷新令牌）
        5. 时间信息（注册时间、最后登录时间）
        
        前端可以通过此接口获取用户的JWT令牌信息，用于后续的API请求认证。
        """
        serializer = UserInfoSerializer(request.user)
        return Response(serializer.data)


# 为TokenBlacklistView添加文档说明
@extend_schema(
    summary="将刷新令牌加入黑名单",
    description="将刷新令牌加入黑名单视图\n\n"
                "此端点用于将有效的刷新令牌加入黑名单，通常在用户登出时调用。\n"
                "加入黑名单的令牌将无法再用于获取新的访问令牌。\n\n"
                "请求体应包含以下字段：\n"
                "- refresh: 需要加入黑名单的刷新令牌\n\n"
                "注意：\n"
                "1. 只有在SIMPLE_JWT设置中BLACKLIST_AFTER_ROTATION为True时才有效。\n"
                "2. 令牌加入黑名单后，在过期时间之前将无法使用。\n"
                "3. 前端应在用户登出时调用此接口以确保安全。",
    request=TokenBlacklistSerializer,
    responses={
        200: None,
        400: {
            'type': 'object',
            'properties': {
                'detail': {'type': 'string', 'description': '错误详情'}
            },
            'description': '请求参数错误或令牌加入黑名单失败'
        }
    },
    tags=["Authentication"]
)
class TokenBlacklistView(BaseTokenBlacklistView):
    """
    将刷新令牌加入黑名单视图

    此端点用于将有效的刷新令牌加入黑名单，通常在用户登出时调用。
    加入黑名单的令牌将无法再用于获取新的访问令牌。

    请求体应包含以下字段：
    - refresh: 需要加入黑名单的刷新令牌

    注意：
    1. 只有在SIMPLE_JWT设置中BLACKLIST_AFTER_ROTATION为True时才有效。
    2. 令牌加入黑名单后，在过期时间之前将无法使用。
    3. 前端应在用户登出时调用此接口以确保安全。
    """
    pass
